package com.mdd.admin.service.order.impl;

import com.alipay.api.AlipayApiException;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.mdd.admin.service.auth.AlipayAuthOrderFreezeService;
import com.mdd.admin.service.bill.OrderBillInfoService;
import com.mdd.admin.service.order.IOrderInfoService;
import com.mdd.admin.service.order.IOrderLeaseDetailsService;
import com.mdd.admin.service.sign.AlipaySignUserAgreementRecordService;
import com.mdd.admin.validate.order.*;
import com.mdd.admin.vo.order.OrderDetailVo;
import com.mdd.admin.vo.order.OrderHandleLogVo;
import com.mdd.admin.vo.order.OrderLeaseDetailVo;
import com.mdd.car.api.VehicleApi;
import com.mdd.common.base.page.PageValidate;
import com.mdd.common.core.PageResult;
import com.mdd.common.entity.OrderBillInfo;
import com.mdd.common.entity.order.OrderDetail;
import com.mdd.common.entity.order.OrderHandleLog;
import com.mdd.common.entity.order.OrderInfo;
import com.mdd.common.entity.order.OrderList;
import com.mdd.common.enums.OrderEnum;
import com.mdd.common.enums.order.status.LeaseOrderStatusEnum;
import com.mdd.common.enums.order.status.OrderVehicleStatusEnum;
import com.mdd.common.enums.order.type.OrderHandleEnum;
import com.mdd.common.mapper.order.OrderHandleLogMapper;
import com.mdd.common.mapper.order.OrderInfoMapper;
import com.mdd.product.entity.LeasingScheme;
import com.mdd.product.entity.ProductSku;
import com.mdd.product.mapper.LeasingSchemeMapper;
import com.mdd.product.mapper.ProductSkuMapper;
import com.mdd.store.entity.Store;
import com.mdd.store.mapper.StoreMapper;
import com.mdd.system.RtAdminThreadLocal;
import com.mdd.system.vo.SystemAuthAdminInformVo;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import javax.annotation.Resource;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.Random;

/**
 * 订单实现类
 * @author LikeAdmin
 */
@Service
public class OrderInfoServiceImpl implements IOrderInfoService {

    @Resource
    OrderInfoMapper orderInfoMapper;
    @Resource
    OrderBillInfoService orderBillInfoService;
    @Resource
    IOrderLeaseDetailsService iOrderLeaseDetailsService;
    @Resource
    VehicleApi vehicleApi;
    @Resource
    StoreMapper storeMapper;
    @Resource
    LeasingSchemeMapper leasingSchemeMapper;
    @Resource
    ProductSkuMapper productSkuMapper;
    @Resource
    AlipayAuthOrderFreezeService alipayAuthOrderFreezeService;
    @Resource
    AlipaySignUserAgreementRecordService alipaySignUserAgreementRecordService;
    @Resource
    OrderHandleLogMapper orderHandleLogMapper;
    /**
     * 订单列表
     *
     * @author LikeAdmin
     * @param pageValidate 分页参数
     * @param searchValidate 搜索参数
     * @return PageResult<OrderInfoListedVo>
     */
    @Override
    public PageResult<OrderList> list(PageValidate pageValidate, OrderInfoSearchValidate searchValidate, SystemAuthAdminInformVo systemAuthAdmin) {
        Integer page  = pageValidate.getPageNo();
        Integer limit = pageValidate.getPageSize();
        if (systemAuthAdmin.getDeptIds().equals(1L)) {
            systemAuthAdmin.setDeptCode("");
        }
        IPage<OrderList> iPage = orderInfoMapper.orderPage(new Page<>(page, limit),systemAuthAdmin.getDeptCode(),
                searchValidate.getOrderType(),searchValidate.getOrderSn(),searchValidate.getStatus());
        return PageResult.iPageHandle(iPage.getTotal(), iPage.getCurrent(), iPage.getSize(), iPage.getRecords());
    }

    /**
     * 订单详情
     * @author LikeAdmin
     * @param orderId 主键参数
     * @return OrderInfo
     */
    @Override
    public OrderDetailVo detail(Long orderId) {
        OrderDetail orderDetail = orderInfoMapper.orderDetailById(orderId);
        Assert.notNull(orderDetail, "订单数据不存在");

        OrderDetailVo vo = new OrderDetailVo();
        BeanUtils.copyProperties(orderDetail, vo);

        OrderHandleLogVo deliverVehicleVo = getOrderHandleLogByOrderId(orderId,OrderHandleEnum.DELIVER_ORDER);
        vo.setDeliverVehicle(deliverVehicleVo);

        OrderHandleLogVo returnVehicleVo = getOrderHandleLogByOrderId(orderId,OrderHandleEnum.RETURN_ORDER);
        vo.setReturnVehicle(returnVehicleVo);
        return vo;
    }

    private OrderHandleLogVo getOrderHandleLogByOrderId(Long orderId,OrderHandleEnum orderHandleEnum) {
        LambdaQueryWrapper<OrderHandleLog> returnLam = new LambdaQueryWrapper<>();
        returnLam.eq(OrderHandleLog::getType,orderHandleEnum.getCode())
                .eq(OrderHandleLog::getOrderId, orderId).orderByDesc(OrderHandleLog::getId).last("limit 1");
        OrderHandleLog orderHandleLog = orderHandleLogMapper.selectOne(returnLam);
        OrderHandleLogVo orderHandleLogVo = new OrderHandleLogVo();
        if(Objects.nonNull(orderHandleLog)) {
            BeanUtils.copyProperties(orderHandleLog, orderHandleLogVo);
        }
        return orderHandleLogVo;
    }

    /**
     * 订单新增
     *
     * @author LikeAdmin
     * @param createValidate 参数
     */
    @Transactional
    @Override
    public void add(OrderInfoCreateValidate createValidate) {
        Store store = storeMapper.selectById(createValidate.getStoreId());
        Assert.notNull(store,"该门店不存在！");

        LeasingScheme leasingScheme = leasingSchemeMapper.selectById(createValidate.getLeasingSchemeId());
        Assert.notNull(leasingScheme,"该租赁计划不存在！");

        ProductSku productSku = productSkuMapper.selectOne(new LambdaQueryWrapper<ProductSku>().eq(ProductSku::getProperties,createValidate.getProperties()));
        Assert.notNull(productSku,"该车品sku不存在！");

        //新增订单基础信息
        OrderInfo model = new OrderInfo();
        model.setOrderSn(generateOrderSn());
        model.setStoreId(store.getId());
        model.setDeptCode(store.getDeptCode());
        model.setUserId(createValidate.getUserId());
        model.setNote(createValidate.getNote());
        orderInfoMapper.insert(model);
    }



    /**
     * 订单编辑
     *
     * @author LikeAdmin
     * @param updateValidate 参数
     */
    @Transactional
    @Override
    public void edit(OrderInfoUpdateValidate updateValidate) {
        OrderInfo model = orderInfoMapper.selectById(updateValidate.getId());
        Assert.notNull(model, "订单数据不存在!");

        model.setId(updateValidate.getId());
        model.setDeptId(updateValidate.getDeptId());
        model.setOrderSn(updateValidate.getOrderSn());
        model.setUserId(updateValidate.getUserId());
        model.setTotalAmount(updateValidate.getTotalAmount());
        model.setPayAmount(updateValidate.getPayAmount());
        model.setSourceType(updateValidate.getSourceType());
        model.setOrderType(updateValidate.getOrderType());
        model.setNote(updateValidate.getNote());
        orderInfoMapper.updateById(model);
    }

    @Transactional
    @Override
    public void addRemark(String orderId, String remark) {
        OrderInfo model = orderInfoMapper.selectById(orderId);
        Assert.notNull(model, "订单数据不存在!");
        model.setRemark(remark);
        orderInfoMapper.updateById(model);
    }
    @Transactional
    @Override
    public void confirm(String orderId) {
        OrderInfo model = orderInfoMapper.selectById(orderId);
        Assert.notNull(model, "订单数据不存在!");
        model.setStatus(OrderEnum.VEHICLE_DELIVERED_ORDER.getCode());
        orderInfoMapper.updateById(model);
    }
    @Override
    @Transactional
    public void finish(Long orderId) throws AlipayApiException {
        OrderInfo model = orderInfoMapper.selectById(orderId);
        Assert.notNull(model, "订单数据不存在!");
        Assert.isTrue(model.getStatus().equals(OrderEnum.UN_SETTLE_ORDER.getCode()),"当前订单状态不能进行完成操作！");
        OrderLeaseDetailVo orderLeaseDetails= iOrderLeaseDetailsService.getOrderLeaseByOrderId(model.getId());
        Assert.isTrue(OrderVehicleStatusEnum.RETURNED_ORDER.getCode().equals(orderLeaseDetails.getOrderVehicleStatus()),"当前订单车辆未还，请先进行还车操作！");
        List<OrderBillInfo> orderBillInfos = orderBillInfoService.getList(model.getId());
        orderBillInfos.forEach(orderBillInfo -> {
                Assert.isTrue(allowFinish(orderBillInfo.getStatus()),"存在完成账单，不能进行完成操作！");
        });

        //取消押金冻结授权
        alipayAuthOrderFreezeService.cancelAuthOrderFreeze(orderId);
        //取消代扣签约
        alipaySignUserAgreementRecordService.cancelRecordByOrderId(orderId);

        model.setStatus(OrderEnum.FINISHED_ORDER.getCode());
        orderInfoMapper.updateById(model);
    }

    @Transactional
    @Override
    public void cancel(Long orderId) throws AlipayApiException {
        OrderInfo model = orderInfoMapper.selectById(orderId);
        Assert.notNull(model, "订单数据不存在!");
        model.setStatus(OrderEnum.CANCEL_ORDER.getCode());
        //取消待处理账单
        orderBillInfoService.cancelBill( orderId );

        //取消押金冻结授权
        alipayAuthOrderFreezeService.cancelAuthOrderFreeze(orderId);
        //取消代扣签约
        alipaySignUserAgreementRecordService.cancelRecordByOrderId(orderId);
        orderInfoMapper.updateById(model);
    }

    /**
     * 订单删除
     * @author LikeAdmin
     * @param id 主键ID
     */
    @Transactional
    @Override
    public void del(Long id) {
        OrderInfo model = orderInfoMapper.selectById(id);

        Assert.notNull(model, "订单数据不存在!");

        orderInfoMapper.deleteById(id);
    }

    public String generateOrderSn() {
        String orderSn = "";
        while (true) {
            // 获取当前时间戳
            long timestamp = System.currentTimeMillis();
            // 获取当前日期
            SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMdd");
            String dateStr = dateFormat.format(System.currentTimeMillis());
            // 获取随机数
            Random random = new Random();
            int randomNum = random.nextInt(1000);
            // 组合订单编号
            orderSn = "O" + dateStr + randomNum + timestamp;
            OrderInfo orderInfo = orderInfoMapper.selectOne(new LambdaQueryWrapper<OrderInfo>()
                    .eq(OrderInfo::getOrderSn, orderSn)
                    .last("limit 1"));
            if (orderInfo == null) {
                break;
            }
            return orderSn;
        }
        return orderSn;
    }
    @Override
    @Transactional
    public void changeCar(OrderBindCarValidate orderBindCarValidate) {
        OrderLeaseDetailVo orderLeaseDetailVo = iOrderLeaseDetailsService.getOrderLeaseByOrderId(orderBindCarValidate.getOrderId());
        orderLeaseDetailVo.setVehicleId(orderBindCarValidate.getCarId());
        Assert.notNull(orderLeaseDetailVo, "数据不存在!");
        //更改原有车辆为待租赁
        if(Objects.nonNull(orderLeaseDetailVo.getVehicleId())){
            vehicleApi.updateState(orderLeaseDetailVo.getVehicleId(),0L);
        }
        iOrderLeaseDetailsService.updateLeaseDetail(orderBindCarValidate.getOrderId(), orderBindCarValidate.getCarId());
        //更改现有车辆为待租赁
        vehicleApi.updateState(orderBindCarValidate.getCarId(),1L);
        OrderInfo orderInfo = orderInfoMapper.selectById(orderBindCarValidate.getOrderId());
        //车辆状态为车辆准备中时 改为 待提车
        if(orderInfo.getStatus().equals( OrderEnum.PREPARATION_ORDER.getCode())){
            orderInfo.setStatus(OrderEnum.VEHICLE_DELIVERED_ORDER.getCode());
            orderInfoMapper.updateById(orderInfo);
        }
    }

    @Override
    public boolean isExist(Long orderId) {
        LambdaQueryWrapper<OrderInfo> orderInfoLq=new LambdaQueryWrapper<>();
        orderInfoLq.eq(OrderInfo::getId,orderId);
        return orderInfoMapper.selectCount(orderInfoLq)>0;
    }

    @Override
    public OrderInfo getOrderInfoById(Long orderId) {
        return orderInfoMapper.selectById(orderId);
    }

    @Override
    @Transactional
    public void deliverVehicle(OrderDeliverVehicleValidate orderDeliverVehicleValidate) {
        OrderInfo orderInfo =orderInfoMapper.selectById(orderDeliverVehicleValidate.getOrderId());
        Assert.isTrue(orderInfo.getStatus().equals(OrderEnum.VEHICLE_DELIVERED_ORDER.getCode()),"该状态不允许进行交车操作！");
        orderInfo.setStatus(OrderEnum.UNDER_WAY.getCode());
        orderInfoMapper.updateById(orderInfo);
        iOrderLeaseDetailsService.updateLeaseDetailStatus(orderDeliverVehicleValidate.getOrderId(), OrderVehicleStatusEnum.DELIVERED_ORDER.getCode());

        OrderHandleLog orderHandleLog =new OrderHandleLog();
        orderHandleLog.setOrderId(orderDeliverVehicleValidate.getOrderId());
        orderHandleLog.setRemark(orderDeliverVehicleValidate.getRemark());
        orderHandleLog.setFileUrls(orderDeliverVehicleValidate.getFileUrls());
        orderHandleLog.setType(OrderHandleEnum.DELIVER_ORDER.getCode());
        orderHandleLog.setCreateTime(new Date());
        orderHandleLog.setCreateUser(RtAdminThreadLocal.getAdminId().toString());
        orderHandleLogMapper.insert(orderHandleLog);
    }

    @Override
    public void returnVehicle(OrderDeliverVehicleValidate orderDeliverVehicleValidate) {
        OrderInfo orderInfo =orderInfoMapper.selectById(orderDeliverVehicleValidate.getOrderId());
        Assert.isTrue(orderInfo.getStatus().equals(OrderEnum.UN_SETTLE_ORDER.getCode()),"该状态不允许进行还车操作！");
        iOrderLeaseDetailsService.updateLeaseDetailStatus(orderDeliverVehicleValidate.getOrderId(), OrderVehicleStatusEnum.RETURNED_ORDER.getCode());

        OrderHandleLog orderHandleLog =new OrderHandleLog();
        orderHandleLog.setOrderId(orderDeliverVehicleValidate.getOrderId());
        orderHandleLog.setRemark(orderDeliverVehicleValidate.getRemark());
        orderHandleLog.setFileUrls(orderDeliverVehicleValidate.getFileUrls());
        orderHandleLog.setType(OrderHandleEnum.RETURN_ORDER.getCode());
        orderHandleLog.setCreateTime(new Date());
        orderHandleLog.setCreateUser(RtAdminThreadLocal.getAdminId().toString());
        orderHandleLogMapper.insert(orderHandleLog);
    }

    @Transactional
    @Override
    public void tradeSuccess(String outOrderNo, String tradeNo) {
        //更新订单状态
        OrderInfo orderInfo = orderInfoMapper.selectOne(new LambdaQueryWrapper<OrderInfo>().eq(OrderInfo::getOrderSn,outOrderNo).last("limit 1"));
        orderInfo.setOutTradeNo(tradeNo);
        orderInfo.setStatus(OrderEnum.PAID_ORDER.getCode());
        orderInfo.setPaymentTime(new Date());
        orderInfoMapper.updateById(orderInfo);
    }

    public Boolean allowFinish(Integer code) {
        return !code.equals(LeaseOrderStatusEnum.TO_BE_ACTIVATED.getCode()) &&
                !code.equals(LeaseOrderStatusEnum.TO_BE_PAID.getCode())
                && !code.equals(LeaseOrderStatusEnum.IN_REVIEW.getCode());
    }
}
